/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package BoardGame.impl;

import BoardGame.BoardGamePackage;
import BoardGame.RuleBuilder;

import MocaTree.File;
import MocaTree.Folder;
import MocaTree.Node;

import SDMLanguage.activities.ActivitiesFactory;
import SDMLanguage.activities.Activity;
import SDMLanguage.activities.ActivityEdge;
import SDMLanguage.activities.ActivityNode;
import SDMLanguage.activities.StartNode;
import SDMLanguage.activities.StopNode;
import SDMLanguage.activities.StoryNode;

import SDMLanguage.patterns.LinkVariable;
import SDMLanguage.patterns.ObjectVariable;
import SDMLanguage.patterns.PatternsFactory;
import SDMLanguage.patterns.StoryPattern;

import de.upb.tools.sdm.*;

import java.lang.reflect.InvocationTargetException;

import java.util.*;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EcoreFactory;

import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.moflon.util.eMoflonEMFUtil;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Rule Builder</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link BoardGame.impl.RuleBuilderImpl#getLastField <em>Last Field</em>}</li>
 *   <li>{@link BoardGame.impl.RuleBuilderImpl#getFigureClass <em>Figure Class</em>}</li>
 *   <li>{@link BoardGame.impl.RuleBuilderImpl#getFieldClass <em>Field Class</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class RuleBuilderImpl extends EObjectImpl implements RuleBuilder {
	/**
	 * The cached value of the '{@link #getLastField() <em>Last Field</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getLastField()
	 * @generated
	 * @ordered
	 */
	protected ObjectVariable lastField;
	/**
	 * The cached value of the '{@link #getFigureClass() <em>Figure Class</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getFigureClass()
	 * @generated
	 * @ordered
	 */
	protected EClass figureClass;
	/**
	 * The cached value of the '{@link #getFieldClass() <em>Field Class</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getFieldClass()
	 * @generated
	 * @ordered
	 */
	protected EClass fieldClass;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected RuleBuilderImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return BoardGamePackage.Literals.RULE_BUILDER;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public ObjectVariable getLastField() {
		if (lastField != null && lastField.eIsProxy()) {
			InternalEObject oldLastField = (InternalEObject) lastField;
			lastField = (ObjectVariable) eResolveProxy(oldLastField);
			if (lastField != oldLastField) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE,
							BoardGamePackage.RULE_BUILDER__LAST_FIELD,
							oldLastField, lastField));
			}
		}
		return lastField;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public ObjectVariable basicGetLastField() {
		return lastField;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setLastField(ObjectVariable newLastField) {
		ObjectVariable oldLastField = lastField;
		lastField = newLastField;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					BoardGamePackage.RULE_BUILDER__LAST_FIELD, oldLastField,
					lastField));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EClass getFigureClass() {
		if (figureClass != null && figureClass.eIsProxy()) {
			InternalEObject oldFigureClass = (InternalEObject) figureClass;
			figureClass = (EClass) eResolveProxy(oldFigureClass);
			if (figureClass != oldFigureClass) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE,
							BoardGamePackage.RULE_BUILDER__FIGURE_CLASS,
							oldFigureClass, figureClass));
			}
		}
		return figureClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EClass basicGetFigureClass() {
		return figureClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setFigureClass(EClass newFigureClass) {
		EClass oldFigureClass = figureClass;
		figureClass = newFigureClass;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					BoardGamePackage.RULE_BUILDER__FIGURE_CLASS,
					oldFigureClass, figureClass));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EClass getFieldClass() {
		if (fieldClass != null && fieldClass.eIsProxy()) {
			InternalEObject oldFieldClass = (InternalEObject) fieldClass;
			fieldClass = (EClass) eResolveProxy(oldFieldClass);
			if (fieldClass != oldFieldClass) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE,
							BoardGamePackage.RULE_BUILDER__FIELD_CLASS,
							oldFieldClass, fieldClass));
			}
		}
		return fieldClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EClass basicGetFieldClass() {
		return fieldClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setFieldClass(EClass newFieldClass) {
		EClass oldFieldClass = fieldClass;
		fieldClass = newFieldClass;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					BoardGamePackage.RULE_BUILDER__FIELD_CLASS, oldFieldClass,
					fieldClass));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EPackage transformFolder(Folder folder, EPackage boardGamePackage) {
		boolean fujaba__Success = false;
		EPackage rulePackage = null;
		Iterator fujaba__IterBoardGamePackageToGenricFigureClass = null;
		Object _TmpObject = null;
		EClass genricFigureClass = null;
		Iterator fujaba__IterBoardGamePackageToFieldClass = null;
		EClass fieldClass = null;
		EClass concreteFigureClass = null;
		EOperation moveTo = null;
		EParameter field = null;
		EAnnotation annotation = null;
		Activity activity = null;
		Node main = null;
		Iterator fujaba__IterFolderToFile = null;
		File file = null;

		// story pattern create a new package for the rules
		try {
			fujaba__Success = false;

			// create object rulePackage
			rulePackage = EcoreFactory.eINSTANCE.createEPackage();
			// assign attribute rulePackage
			rulePackage.setNsPrefix("GameRules");
			// assign attribute rulePackage
			rulePackage.setNsURI("http://www.moflon.org.GameRules");
			// assign attribute rulePackage
			rulePackage.setName("GameRules");
			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		// story pattern for all files in the parsed MocaTree
		try {
			fujaba__Success = false;

			// check object folder is really bound
			JavaSDM.ensure(folder != null);
			// iterate to-many link file from folder to file
			fujaba__Success = false;

			fujaba__IterFolderToFile = new ArrayList(folder.getFile())
					.iterator();

			while (fujaba__IterFolderToFile.hasNext()) {
				try {
					file = (File) fujaba__IterFolderToFile.next();

					// check object file is really bound
					JavaSDM.ensure(file != null);
					// bind object
					main = file.getRootNode();

					// check object main is really bound
					JavaSDM.ensure(main != null);

					// story pattern create new FigureClass with moveTo EOperation
					try {
						fujaba__Success = false;

						// check object boardGamePackage is really bound
						JavaSDM.ensure(boardGamePackage != null);
						// check object rulePackage is really bound
						JavaSDM.ensure(rulePackage != null);
						// check isomorphic binding between objects rulePackage and boardGamePackage
						JavaSDM.ensure(!rulePackage.equals(boardGamePackage));

						// iterate to-many link eClassifiers from boardGamePackage to fieldClass
						fujaba__Success = false;

						fujaba__IterBoardGamePackageToFieldClass = boardGamePackage
								.getEClassifiers().iterator();

						while (!(fujaba__Success)
								&& fujaba__IterBoardGamePackageToFieldClass
										.hasNext()) {
							try {
								_TmpObject = fujaba__IterBoardGamePackageToFieldClass
										.next();

								// ensure correct type and really bound of object fieldClass
								JavaSDM.ensure(_TmpObject instanceof EClass);
								fieldClass = (EClass) _TmpObject;

								// attribute condition
								JavaSDM.ensure(JavaSDM.stringCompare(
										fieldClass.getName(), "Field") == 0);

								// iterate to-many link eClassifiers from boardGamePackage to genricFigureClass
								fujaba__Success = false;

								fujaba__IterBoardGamePackageToGenricFigureClass = boardGamePackage
										.getEClassifiers().iterator();

								while (!(fujaba__Success)
										&& fujaba__IterBoardGamePackageToGenricFigureClass
												.hasNext()) {
									try {
										_TmpObject = fujaba__IterBoardGamePackageToGenricFigureClass
												.next();

										// ensure correct type and really bound of object genricFigureClass
										JavaSDM.ensure(_TmpObject instanceof EClass);
										genricFigureClass = (EClass) _TmpObject;

										// check isomorphic binding between objects genricFigureClass and fieldClass
										JavaSDM.ensure(!genricFigureClass
												.equals(fieldClass));

										// attribute condition
										JavaSDM.ensure(JavaSDM.stringCompare(
												genricFigureClass.getName(),
												"Figure") == 0);

										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}
								}
								JavaSDM.ensure(fujaba__Success);

								fujaba__Success = true;
							} catch (JavaSDMException fujaba__InternalException) {
								fujaba__Success = false;
							}
						}
						JavaSDM.ensure(fujaba__Success);
						// create object concreteFigureClass
						concreteFigureClass = EcoreFactory.eINSTANCE
								.createEClass();
						// create object moveTo
						moveTo = EcoreFactory.eINSTANCE.createEOperation();
						// create object field
						field = EcoreFactory.eINSTANCE.createEParameter();
						// create object annotation
						annotation = EcoreFactory.eINSTANCE.createEAnnotation();
						// assign attribute concreteFigureClass
						concreteFigureClass.setName(file.getName());
						// assign attribute moveTo
						moveTo.setName("moveTo");
						// assign attribute field
						field.setName("field");
						// assign attribute annotation
						annotation.setSource("SDM");
						// create link
						org.moflon.util.eMoflonEMFUtil.addOppositeReference(
								this, fieldClass, "fieldClass");
						// create link
						org.moflon.util.eMoflonEMFUtil.addOppositeReference(
								this, genricFigureClass, "figureClass");
						// create link
						concreteFigureClass.getESuperTypes().add(
								genricFigureClass);

						// create link
						org.moflon.util.eMoflonEMFUtil.addOppositeReference(
								concreteFigureClass, moveTo, "eOperations");
						// create link
						rulePackage.getEClassifiers().add(concreteFigureClass);

						// create link
						org.moflon.util.eMoflonEMFUtil.addOppositeReference(
								moveTo, field, "eParameters");
						// create link
						annotation.setEModelElement(moveTo);

						// create link
						org.moflon.util.eMoflonEMFUtil.addOppositeReference(
								field, fieldClass, "eType");
						fujaba__Success = true;
					} catch (JavaSDMException fujaba__InternalException) {
						fujaba__Success = false;
					}

					// story pattern process file node in the MocaTree
					try {
						fujaba__Success = false;

						_TmpObject = (this.transformFile(main));

						// ensure correct type and really bound of object activity
						JavaSDM.ensure(_TmpObject instanceof Activity);
						activity = (Activity) _TmpObject;

						fujaba__Success = true;
					} catch (JavaSDMException fujaba__InternalException) {
						fujaba__Success = false;
					}

					this.embed(activity, annotation);

					fujaba__Success = true;
				} catch (JavaSDMException fujaba__InternalException) {
					fujaba__Success = false;
				}
			}
			JavaSDM.ensure(fujaba__Success);
			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		return rulePackage;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Activity transformFile(Node root) {
		boolean fujaba__Success = false;
		Activity newActvity = null;
		StopNode stop = null;
		ActivityEdge initialEdge = null;
		StartNode start = null;
		ActivityNode firstNode = null;
		StoryNode newActivityNode = null;
		ActivityEdge newFailEdge = null;
		ActivityEdge newSuccessEdge = null;
		StopNode newStopNode = null;
		Object _TmpObject = null;
		StoryPattern pattern = null;
		Iterator fujaba__IterRootToRule = null;
		Node rule = null;

		// story pattern create basic initial control flow, i.e., a new activity with a start and stop node
		try {
			fujaba__Success = false;

			// create object newActvity
			newActvity = ActivitiesFactory.eINSTANCE.createActivity();
			// create object stop
			stop = ActivitiesFactory.eINSTANCE.createStopNode();
			// create object initialEdge
			initialEdge = ActivitiesFactory.eINSTANCE.createActivityEdge();
			// create object start
			start = ActivitiesFactory.eINSTANCE.createStartNode();
			// create link
			stop.setOwningActivity(newActvity);

			// create link
			initialEdge.setOwningActivity(newActvity);

			// create link
			start.setOwningActivity(newActvity);

			// create link
			initialEdge.setSource(start);

			// create link
			initialEdge.setTarget(stop);

			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		// story pattern for all rules
		try {
			fujaba__Success = false;

			// check object root is really bound
			JavaSDM.ensure(root != null);
			// iterate to-many link children from root to rule
			fujaba__Success = false;

			fujaba__IterRootToRule = new ArrayList(root.getChildren())
					.iterator();

			while (fujaba__IterRootToRule.hasNext()) {
				try {
					_TmpObject = fujaba__IterRootToRule.next();

					// ensure correct type and really bound of object rule
					JavaSDM.ensure(_TmpObject instanceof Node);
					rule = (Node) _TmpObject;

					// check isomorphic binding between objects rule and root
					JavaSDM.ensure(!rule.equals(root));

					// attribute condition
					JavaSDM.ensure(JavaSDM.stringCompare(rule.getName(), "RULE") == 0);

					// story pattern add new activity node for the rule; the activity node is added between the start and the second node;
					try {
						fujaba__Success = false;

						// check object initialEdge is really bound
						JavaSDM.ensure(initialEdge != null);
						// check object newActvity is really bound
						JavaSDM.ensure(newActvity != null);
						// check object start is really bound
						JavaSDM.ensure(start != null);
						// check link source from initialEdge to start
						JavaSDM.ensure(start.equals(initialEdge.getSource()));

						// bind object
						firstNode = initialEdge.getTarget();

						// check object firstNode is really bound
						JavaSDM.ensure(firstNode != null);

						// check isomorphic binding between objects start and firstNode
						JavaSDM.ensure(!start.equals(firstNode));

						// destroy link
						initialEdge.setTarget(null);
						// create object newActivityNode
						newActivityNode = ActivitiesFactory.eINSTANCE
								.createStoryNode();
						// create object newFailEdge
						newFailEdge = ActivitiesFactory.eINSTANCE
								.createActivityEdge();
						// create object newSuccessEdge
						newSuccessEdge = ActivitiesFactory.eINSTANCE
								.createActivityEdge();
						// create object newStopNode
						newStopNode = ActivitiesFactory.eINSTANCE
								.createStopNode();
						// assign attribute newFailEdge
						newFailEdge
								.setGuard(SDMLanguage.activities.EdgeGuard.FAILURE);
						// assign attribute newSuccessEdge
						newSuccessEdge
								.setGuard(SDMLanguage.activities.EdgeGuard.SUCCESS);
						// create link
						newActivityNode.setOwningActivity(newActvity);

						// create link
						newFailEdge.setOwningActivity(newActvity);

						// create link
						newSuccessEdge.setOwningActivity(newActvity);

						// create link
						newStopNode.setOwningActivity(newActvity);

						// create link
						initialEdge.setTarget(newActivityNode);

						// create link
						newFailEdge.setSource(newActivityNode);

						// create link
						newSuccessEdge.setSource(newActivityNode);

						// create link
						newFailEdge.setTarget(firstNode);

						// create link
						newStopNode.getIncoming().add(newSuccessEdge);

						fujaba__Success = true;
					} catch (JavaSDMException fujaba__InternalException) {
						fujaba__Success = false;
					}

					// story pattern create StoryPattern for new ActivityNode by processing the rule
					try {
						fujaba__Success = false;

						_TmpObject = (this.transformRule(rule));

						// ensure correct type and really bound of object pattern
						JavaSDM.ensure(_TmpObject instanceof StoryPattern);
						pattern = (StoryPattern) _TmpObject;

						// check object newActivityNode is really bound
						JavaSDM.ensure(newActivityNode != null);
						// create link
						pattern.setStoryNode(newActivityNode);

						fujaba__Success = true;
					} catch (JavaSDMException fujaba__InternalException) {
						fujaba__Success = false;
					}

					fujaba__Success = true;
				} catch (JavaSDMException fujaba__InternalException) {
					fujaba__Success = false;
				}
			}
			JavaSDM.ensure(fujaba__Success);
			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		return newActvity;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void embed(Activity activity, EAnnotation annotation) {
		eMoflonEMFUtil.embedSDMInEAnnotation(activity, annotation);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public StoryPattern transformRule(Node ruleNode) {
		boolean fujaba__Success = false;
		ObjectVariable previousFromLastRun = null;
		EClass figureClass = null;
		EClass fieldClass = null;
		StoryPattern pattern = null;
		ObjectVariable thisOV = null;
		Iterator fujaba__IterRowNodeBeforeToFirstFieldNode = null;
		Object _TmpObject = null;
		Node firstFieldNode = null;
		Iterator fujaba__IterRowNodeAfterToFirstFieldNodeAfter = null;
		Node firstFieldNodeAfter = null;
		Iterator fujaba__IterAfterNodeToRowNodeAfter = null;
		Node rowNodeAfter = null;
		ObjectVariable firstFieldOV = null;
		ObjectVariable previousOV = null;
		LinkVariable linkToPreviousOV = null;
		Iterator fujaba__IterRowNodeAfterToCurrentFieldNodeAfter = null;
		Node currentFieldNodeAfter = null;
		ObjectVariable currentFieldOV = null;
		Iterator fujaba__IterRowNodeBeforeToCurrentFieldNode = null;
		Node currentFieldNode = null;
		Iterator fujaba__IterBeforeNodeToRowNodeBefore = null;
		Node rowNodeBefore = null;
		Iterator fujaba__IterRuleNodeToBeforeNode = null;
		Node beforeNode = null;
		Iterator fujaba__IterRuleNodeToAfterNode = null;
		Node afterNode = null;

		// story pattern prepare variables for this and target field
		try {
			fujaba__Success = false;

			// bind object
			previousFromLastRun = this.getLastField();

			// bind object
			fieldClass = this.getFieldClass();

			// check object fieldClass is really bound
			JavaSDM.ensure(fieldClass != null);

			// bind object
			figureClass = this.getFigureClass();

			// check object figureClass is really bound
			JavaSDM.ensure(figureClass != null);

			// check isomorphic binding between objects figureClass and fieldClass
			JavaSDM.ensure(!figureClass.equals(fieldClass));

			// check optional
			if (previousFromLastRun != null) {
				// destroy link
				this.setLastField(null);
			}// create object pattern
			pattern = PatternsFactory.eINSTANCE.createStoryPattern();
			// create object thisOV
			thisOV = PatternsFactory.eINSTANCE.createObjectVariable();
			// assign attribute thisOV
			thisOV.setName("this");
			// assign attribute thisOV
			thisOV.setBindingOperator(SDMLanguage.patterns.BindingOperator.CHECK_ONLY);
			// assign attribute thisOV
			thisOV.setBindingSemantics(SDMLanguage.patterns.BindingSemantics.MANDATORY);
			// assign attribute thisOV
			thisOV.setBindingState(SDMLanguage.patterns.BindingState.BOUND);
			// create link
			thisOV.setPattern(pattern);

			// create link
			org.moflon.util.eMoflonEMFUtil.addOppositeReference(thisOV,
					figureClass, "type");
			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		// story pattern for all rows
		try {
			fujaba__Success = false;

			// check object ruleNode is really bound
			JavaSDM.ensure(ruleNode != null);
			// iterate to-many link children from ruleNode to afterNode
			fujaba__Success = false;

			fujaba__IterRuleNodeToAfterNode = new ArrayList(
					ruleNode.getChildren()).iterator();

			while (fujaba__IterRuleNodeToAfterNode.hasNext()) {
				try {
					_TmpObject = fujaba__IterRuleNodeToAfterNode.next();

					// ensure correct type and really bound of object afterNode
					JavaSDM.ensure(_TmpObject instanceof Node);
					afterNode = (Node) _TmpObject;

					// check isomorphic binding between objects ruleNode and afterNode
					JavaSDM.ensure(!ruleNode.equals(afterNode));

					// iterate to-many link children from ruleNode to beforeNode
					fujaba__Success = false;

					fujaba__IterRuleNodeToBeforeNode = new ArrayList(
							ruleNode.getChildren()).iterator();

					while (fujaba__IterRuleNodeToBeforeNode.hasNext()) {
						try {
							_TmpObject = fujaba__IterRuleNodeToBeforeNode
									.next();

							// ensure correct type and really bound of object beforeNode
							JavaSDM.ensure(_TmpObject instanceof Node);
							beforeNode = (Node) _TmpObject;

							// check isomorphic binding between objects beforeNode and afterNode
							JavaSDM.ensure(!beforeNode.equals(afterNode));

							// check isomorphic binding between objects ruleNode and beforeNode
							JavaSDM.ensure(!ruleNode.equals(beforeNode));

							// iterate to-many link children from beforeNode to rowNodeBefore
							fujaba__Success = false;

							fujaba__IterBeforeNodeToRowNodeBefore = new ArrayList(
									beforeNode.getChildren()).iterator();

							while (fujaba__IterBeforeNodeToRowNodeBefore
									.hasNext()) {
								try {
									_TmpObject = fujaba__IterBeforeNodeToRowNodeBefore
											.next();

									// ensure correct type and really bound of object rowNodeBefore
									JavaSDM.ensure(_TmpObject instanceof Node);
									rowNodeBefore = (Node) _TmpObject;

									// check isomorphic binding between objects rowNodeBefore and afterNode
									JavaSDM.ensure(!rowNodeBefore
											.equals(afterNode));

									// check isomorphic binding between objects rowNodeBefore and beforeNode
									JavaSDM.ensure(!rowNodeBefore
											.equals(beforeNode));

									// check isomorphic binding between objects ruleNode and rowNodeBefore
									JavaSDM.ensure(!ruleNode
											.equals(rowNodeBefore));

									// attribute condition
									JavaSDM.ensure(JavaSDM.stringCompare(
											afterNode.getName(), "AFTER") == 0);

									// attribute condition
									JavaSDM.ensure(JavaSDM.stringCompare(
											beforeNode.getName(), "BEFORE") == 0);

									// attribute condition
									JavaSDM.ensure(JavaSDM.stringCompare(
											rowNodeBefore.getName(), "ROW") == 0);

									// story pattern handle first field in a Row; i.e. match the first field of a row in subtree "before" and "after"
									try {
										fujaba__Success = false;

										// check object afterNode is really bound
										JavaSDM.ensure(afterNode != null);
										// check object rowNodeBefore is really bound
										JavaSDM.ensure(rowNodeBefore != null);
										// check isomorphic binding between objects rowNodeBefore and afterNode
										JavaSDM.ensure(!rowNodeBefore
												.equals(afterNode));

										// iterate to-many link children from afterNode to rowNodeAfter
										fujaba__Success = false;

										fujaba__IterAfterNodeToRowNodeAfter = afterNode
												.getChildren().iterator();

										while (!(fujaba__Success)
												&& fujaba__IterAfterNodeToRowNodeAfter
														.hasNext()) {
											try {
												_TmpObject = fujaba__IterAfterNodeToRowNodeAfter
														.next();

												// ensure correct type and really bound of object rowNodeAfter
												JavaSDM.ensure(_TmpObject instanceof Node);
												rowNodeAfter = (Node) _TmpObject;

												// check isomorphic binding between objects rowNodeAfter and afterNode
												JavaSDM.ensure(!rowNodeAfter
														.equals(afterNode));

												// check isomorphic binding between objects rowNodeBefore and rowNodeAfter
												JavaSDM.ensure(!rowNodeBefore
														.equals(rowNodeAfter));

												// attribute condition
												JavaSDM.ensure(rowNodeAfter
														.getIndex() == rowNodeBefore
														.getIndex());

												// attribute condition
												JavaSDM.ensure(JavaSDM.stringCompare(
														rowNodeAfter.getName(),
														"ROW") == 0);

												// iterate to-many link children from rowNodeAfter to firstFieldNodeAfter
												fujaba__Success = false;

												fujaba__IterRowNodeAfterToFirstFieldNodeAfter = rowNodeAfter
														.getChildren()
														.iterator();

												while (!(fujaba__Success)
														&& fujaba__IterRowNodeAfterToFirstFieldNodeAfter
																.hasNext()) {
													try {
														_TmpObject = fujaba__IterRowNodeAfterToFirstFieldNodeAfter
																.next();

														// ensure correct type and really bound of object firstFieldNodeAfter
														JavaSDM.ensure(_TmpObject instanceof Node);
														firstFieldNodeAfter = (Node) _TmpObject;

														// check isomorphic binding between objects firstFieldNodeAfter and afterNode
														JavaSDM.ensure(!firstFieldNodeAfter
																.equals(afterNode));

														// check isomorphic binding between objects rowNodeAfter and firstFieldNodeAfter
														JavaSDM.ensure(!rowNodeAfter
																.equals(firstFieldNodeAfter));

														// check isomorphic binding between objects rowNodeBefore and firstFieldNodeAfter
														JavaSDM.ensure(!rowNodeBefore
																.equals(firstFieldNodeAfter));

														// attribute condition
														JavaSDM.ensure(firstFieldNodeAfter
																.getIndex() == 0);

														// iterate to-many link children from rowNodeBefore to firstFieldNode
														fujaba__Success = false;

														fujaba__IterRowNodeBeforeToFirstFieldNode = rowNodeBefore
																.getChildren()
																.iterator();

														while (!(fujaba__Success)
																&& fujaba__IterRowNodeBeforeToFirstFieldNode
																		.hasNext()) {
															try {
																_TmpObject = fujaba__IterRowNodeBeforeToFirstFieldNode
																		.next();

																// ensure correct type and really bound of object firstFieldNode
																JavaSDM.ensure(_TmpObject instanceof Node);
																firstFieldNode = (Node) _TmpObject;

																// check isomorphic binding between objects firstFieldNode and afterNode
																JavaSDM.ensure(!firstFieldNode
																		.equals(afterNode));

																// check isomorphic binding between objects firstFieldNodeAfter and firstFieldNode
																JavaSDM.ensure(!firstFieldNodeAfter
																		.equals(firstFieldNode));

																// check isomorphic binding between objects rowNodeAfter and firstFieldNode
																JavaSDM.ensure(!rowNodeAfter
																		.equals(firstFieldNode));

																// check isomorphic binding between objects rowNodeBefore and firstFieldNode
																JavaSDM.ensure(!rowNodeBefore
																		.equals(firstFieldNode));

																// attribute condition
																JavaSDM.ensure(firstFieldNode
																		.getIndex() == 0);

																fujaba__Success = true;
															} catch (JavaSDMException fujaba__InternalException) {
																fujaba__Success = false;
															}
														}
														JavaSDM.ensure(fujaba__Success);

														fujaba__Success = true;
													} catch (JavaSDMException fujaba__InternalException) {
														fujaba__Success = false;
													}
												}
												JavaSDM.ensure(fujaba__Success);

												fujaba__Success = true;
											} catch (JavaSDMException fujaba__InternalException) {
												fujaba__Success = false;
											}
										}
										JavaSDM.ensure(fujaba__Success);
										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}

									// story pattern For every row crate the first field of the row
									try {
										fujaba__Success = false;

										_TmpObject = (this.transformField(
												pattern, thisOV,
												firstFieldNode,
												firstFieldNodeAfter));

										// ensure correct type and really bound of object firstFieldOV
										JavaSDM.ensure(_TmpObject instanceof ObjectVariable);
										firstFieldOV = (ObjectVariable) _TmpObject;

										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}

									// story pattern check if last field reference of the Rule builder (stores the first field of the row previously processed) exists (if true: not the first row; if false: first row processed)
									try {
										fujaba__Success = false;

										// bind object
										previousOV = this.getLastField();

										// check object previousOV is really bound
										JavaSDM.ensure(previousOV != null);

										// destroy link
										org.moflon.util.eMoflonEMFUtil
												.removeOppositeReference(this,
														previousOV, "lastField");
										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}

									if (fujaba__Success) {
										// story pattern create a link to first field of the previous row
										try {
											fujaba__Success = false;

											// check object firstFieldOV is really bound
											JavaSDM.ensure(firstFieldOV != null);
											// check object pattern is really bound
											JavaSDM.ensure(pattern != null);
											// check object previousOV is really bound
											JavaSDM.ensure(previousOV != null);
											// check isomorphic binding between objects previousOV and firstFieldOV
											JavaSDM.ensure(!previousOV
													.equals(firstFieldOV));

											// create object linkToPreviousOV
											linkToPreviousOV = PatternsFactory.eINSTANCE
													.createLinkVariable();
											// assign attribute linkToPreviousOV
											linkToPreviousOV
													.setName("NeighbourNorth");
											// create link
											pattern.getLinkVariable().add(
													linkToPreviousOV);

											// create link
											previousOV.getIncomingLink().add(
													linkToPreviousOV);

											// create link
											firstFieldOV.getOutgoingLink().add(
													linkToPreviousOV);

											fujaba__Success = true;
										} catch (JavaSDMException fujaba__InternalException) {
											fujaba__Success = false;
										}

									} else {

									}
									// story pattern set last field reference to first field of the current row
									try {
										fujaba__Success = false;

										// check object firstFieldOV is really bound
										JavaSDM.ensure(firstFieldOV != null);
										// create link
										org.moflon.util.eMoflonEMFUtil
												.addOppositeReference(this,
														firstFieldOV,
														"lastField");
										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}

									// story pattern for all remaining field nodes in the row of the before sub(Moca)tree
									try {
										fujaba__Success = false;

										// check object rowNodeBefore is really bound
										JavaSDM.ensure(rowNodeBefore != null);
										// iterate to-many link children from rowNodeBefore to currentFieldNode
										fujaba__Success = false;

										fujaba__IterRowNodeBeforeToCurrentFieldNode = new ArrayList(
												rowNodeBefore.getChildren())
												.iterator();

										while (fujaba__IterRowNodeBeforeToCurrentFieldNode
												.hasNext()) {
											try {
												_TmpObject = fujaba__IterRowNodeBeforeToCurrentFieldNode
														.next();

												// ensure correct type and really bound of object currentFieldNode
												JavaSDM.ensure(_TmpObject instanceof Node);
												currentFieldNode = (Node) _TmpObject;

												// check isomorphic binding between objects rowNodeBefore and currentFieldNode
												JavaSDM.ensure(!rowNodeBefore
														.equals(currentFieldNode));

												// attribute condition
												JavaSDM.ensure(currentFieldNode
														.getIndex() > 0);

												// story pattern fetch the corresponding node (same index) in the after subtree
												try {
													fujaba__Success = false;

													// check object rowNodeAfter is really bound
													JavaSDM.ensure(rowNodeAfter != null);
													// iterate to-many link children from rowNodeAfter to currentFieldNodeAfter
													fujaba__Success = false;

													fujaba__IterRowNodeAfterToCurrentFieldNodeAfter = rowNodeAfter
															.getChildren()
															.iterator();

													while (!(fujaba__Success)
															&& fujaba__IterRowNodeAfterToCurrentFieldNodeAfter
																	.hasNext()) {
														try {
															_TmpObject = fujaba__IterRowNodeAfterToCurrentFieldNodeAfter
																	.next();

															// ensure correct type and really bound of object currentFieldNodeAfter
															JavaSDM.ensure(_TmpObject instanceof Node);
															currentFieldNodeAfter = (Node) _TmpObject;

															// check isomorphic binding between objects rowNodeAfter and currentFieldNodeAfter
															JavaSDM.ensure(!rowNodeAfter
																	.equals(currentFieldNodeAfter));

															// attribute condition
															JavaSDM.ensure(currentFieldNodeAfter
																	.getIndex() == currentFieldNode
																	.getIndex());

															fujaba__Success = true;
														} catch (JavaSDMException fujaba__InternalException) {
															fujaba__Success = false;
														}
													}
													JavaSDM.ensure(fujaba__Success);
													fujaba__Success = true;
												} catch (JavaSDMException fujaba__InternalException) {
													fujaba__Success = false;
												}

												// story pattern Create a new Field Object Variable and add it to the story pattern; create a like to the firstFieldOV ( the previously prcessed field in a row)
												try {
													fujaba__Success = false;

													_TmpObject = (this
															.transformField(
																	pattern,
																	thisOV,
																	currentFieldNode,
																	currentFieldNodeAfter));

													// ensure correct type and really bound of object currentFieldOV
													JavaSDM.ensure(_TmpObject instanceof ObjectVariable);
													currentFieldOV = (ObjectVariable) _TmpObject;

													// check object firstFieldOV is really bound
													JavaSDM.ensure(firstFieldOV != null);
													// check object pattern is really bound
													JavaSDM.ensure(pattern != null);
													// check isomorphic binding between objects firstFieldOV and currentFieldOV
													JavaSDM.ensure(!firstFieldOV
															.equals(currentFieldOV));

													// create object linkToPreviousOV
													linkToPreviousOV = PatternsFactory.eINSTANCE
															.createLinkVariable();
													// assign attribute linkToPreviousOV
													linkToPreviousOV
															.setName("NeighbourEast");
													// create link
													linkToPreviousOV
															.setPattern(pattern);

													// create link
													linkToPreviousOV
															.setTarget(currentFieldOV);

													// create link
													linkToPreviousOV
															.setSource(firstFieldOV);

													fujaba__Success = true;
												} catch (JavaSDMException fujaba__InternalException) {
													fujaba__Success = false;
												}

												// story pattern set firstFieldOV to currentfieldOV
												try {
													fujaba__Success = false;

													_TmpObject = currentFieldOV;

													// ensure correct type and really bound of object firstFieldOV
													JavaSDM.ensure(_TmpObject instanceof ObjectVariable);
													firstFieldOV = (ObjectVariable) _TmpObject;

													fujaba__Success = true;
												} catch (JavaSDMException fujaba__InternalException) {
													fujaba__Success = false;
												}

												fujaba__Success = true;
											} catch (JavaSDMException fujaba__InternalException) {
												fujaba__Success = false;
											}
										}
										JavaSDM.ensure(fujaba__Success);
										fujaba__Success = true;
									} catch (JavaSDMException fujaba__InternalException) {
										fujaba__Success = false;
									}

									fujaba__Success = true;
								} catch (JavaSDMException fujaba__InternalException) {
									fujaba__Success = false;
								}
							}
							JavaSDM.ensure(fujaba__Success);

							fujaba__Success = true;
						} catch (JavaSDMException fujaba__InternalException) {
							fujaba__Success = false;
						}
					}
					JavaSDM.ensure(fujaba__Success);

					fujaba__Success = true;
				} catch (JavaSDMException fujaba__InternalException) {
					fujaba__Success = false;
				}
			}
			JavaSDM.ensure(fujaba__Success);
			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		return pattern;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public ObjectVariable transformField(StoryPattern pattern,
			ObjectVariable figureOV, Node before, Node after) {
		boolean fujaba__Success = false;
		EClass fieldClass = null;
		ObjectVariable createdFieldOV = null;
		LinkVariable link = null;
		EClass figureClass = null;
		LinkVariable ovToFigure = null;
		ObjectVariable noFigure = null;

		// story pattern create a new Field Object Variable; set type to fieldClass; add it to the story pattern
		try {
			fujaba__Success = false;

			// check object pattern is really bound
			JavaSDM.ensure(pattern != null);
			// bind object
			fieldClass = this.getFieldClass();

			// check object fieldClass is really bound
			JavaSDM.ensure(fieldClass != null);

			// create object createdFieldOV
			createdFieldOV = PatternsFactory.eINSTANCE.createObjectVariable();
			// assign attribute createdFieldOV
			createdFieldOV.setName("field" + before.getParentNode().getIndex()
					+ before.getIndex());
			// assign attribute createdFieldOV
			createdFieldOV
					.setBindingOperator(SDMLanguage.patterns.BindingOperator.CHECK_ONLY);
			// assign attribute createdFieldOV
			createdFieldOV
					.setBindingSemantics(SDMLanguage.patterns.BindingSemantics.MANDATORY);
			// assign attribute createdFieldOV
			createdFieldOV
					.setBindingState(SDMLanguage.patterns.BindingState.UNBOUND);
			// create link
			createdFieldOV.setType(fieldClass);

			// create link
			pattern.getObjectVariable().add(createdFieldOV);

			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		// story pattern If before node (representing a field in the before sub(Moca)tree) is labeled with "THIS_FIELD" (# in textual syntax) then create link from the figure to corresponding field (indicating that figure is on the created field) and mark it as "DESTROY"
		try {
			fujaba__Success = false;

			// check object before is really bound
			JavaSDM.ensure(before != null);
			// check object createdFieldOV is really bound
			JavaSDM.ensure(createdFieldOV != null);
			// check object figureOV is really bound
			JavaSDM.ensure(figureOV != null);
			// check object pattern is really bound
			JavaSDM.ensure(pattern != null);
			// check isomorphic binding between objects figureOV and createdFieldOV
			JavaSDM.ensure(!figureOV.equals(createdFieldOV));

			// attribute condition
			JavaSDM.ensure(JavaSDM.stringCompare(before.getName(), "THIS_FIELD") == 0);

			// create object link
			link = PatternsFactory.eINSTANCE.createLinkVariable();
			// assign attribute createdFieldOV
			createdFieldOV.setName("currentField");
			// assign attribute link
			link.setName("field");
			// assign attribute link
			link.setBindingOperator(SDMLanguage.patterns.BindingOperator.DESTROY);
			// create link
			link.setTarget(createdFieldOV);

			// create link
			link.setSource(figureOV);

			// create link
			pattern.getLinkVariable().add(link);

			fujaba__Success = true;
		} catch (JavaSDMException fujaba__InternalException) {
			fujaba__Success = false;
		}

		if (fujaba__Success) {

		} else {
			// story pattern If after node (representing a field in the after sub(Moca)tree) is labeled with "THIS_FIELD" then create link from the figure to corresponding field (indicating that figure has to be moved on created field) and mark it as "CREATE"
			try {
				fujaba__Success = false;

				// check object after is really bound
				JavaSDM.ensure(after != null);
				// check object createdFieldOV is really bound
				JavaSDM.ensure(createdFieldOV != null);
				// check object figureOV is really bound
				JavaSDM.ensure(figureOV != null);
				// check object pattern is really bound
				JavaSDM.ensure(pattern != null);
				// check isomorphic binding between objects figureOV and createdFieldOV
				JavaSDM.ensure(!figureOV.equals(createdFieldOV));

				// attribute condition
				JavaSDM.ensure(JavaSDM.stringCompare(after.getName(),
						"THIS_FIELD") == 0);

				// create object link
				link = PatternsFactory.eINSTANCE.createLinkVariable();
				// assign attribute createdFieldOV
				createdFieldOV.setName("field");
				// assign attribute createdFieldOV
				createdFieldOV
						.setBindingState(SDMLanguage.patterns.BindingState.BOUND);
				// assign attribute link
				link.setBindingOperator(SDMLanguage.patterns.BindingOperator.CREATE);
				// assign attribute link
				link.setName("field");
				// create link
				link.setTarget(createdFieldOV);

				// create link
				figureOV.getOutgoingLink().add(link);

				// create link
				pattern.getLinkVariable().add(link);

				fujaba__Success = true;
			} catch (JavaSDMException fujaba__InternalException) {
				fujaba__Success = false;
			}

			// story pattern If before node (representing a field in the before sub(Moca)tree) is labeled with "EMPTY_FIELD" then create a NAC that ensures that no figure is on this field
			try {
				fujaba__Success = false;

				// check object before is really bound
				JavaSDM.ensure(before != null);
				// check object createdFieldOV is really bound
				JavaSDM.ensure(createdFieldOV != null);
				// check object pattern is really bound
				JavaSDM.ensure(pattern != null);
				// bind object
				figureClass = this.getFigureClass();

				// check object figureClass is really bound
				JavaSDM.ensure(figureClass != null);

				// attribute condition
				JavaSDM.ensure(JavaSDM.stringCompare(before.getName(),
						"EMPTY_FIELD") == 0);

				// create object ovToFigure
				ovToFigure = PatternsFactory.eINSTANCE.createLinkVariable();
				// create object noFigure
				noFigure = PatternsFactory.eINSTANCE.createObjectVariable();
				// assign attribute noFigure
				noFigure.setBindingSemantics(SDMLanguage.patterns.BindingSemantics.NEGATIVE);
				// assign attribute noFigure
				noFigure.setName("noFigure");
				// assign attribute ovToFigure
				ovToFigure.setName("figure");
				// create link
				ovToFigure.setSource(createdFieldOV);

				// create link
				noFigure.setPattern(pattern);

				// create link
				ovToFigure.setPattern(pattern);

				// create link
				org.moflon.util.eMoflonEMFUtil.addOppositeReference(noFigure,
						figureClass, "type");
				// create link
				ovToFigure.setTarget(noFigure);

				fujaba__Success = true;
			} catch (JavaSDMException fujaba__InternalException) {
				fujaba__Success = false;
			}

		}
		return createdFieldOV;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
		case BoardGamePackage.RULE_BUILDER__LAST_FIELD:
			if (resolve)
				return getLastField();
			return basicGetLastField();
		case BoardGamePackage.RULE_BUILDER__FIGURE_CLASS:
			if (resolve)
				return getFigureClass();
			return basicGetFigureClass();
		case BoardGamePackage.RULE_BUILDER__FIELD_CLASS:
			if (resolve)
				return getFieldClass();
			return basicGetFieldClass();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
		case BoardGamePackage.RULE_BUILDER__LAST_FIELD:
			setLastField((ObjectVariable) newValue);
			return;
		case BoardGamePackage.RULE_BUILDER__FIGURE_CLASS:
			setFigureClass((EClass) newValue);
			return;
		case BoardGamePackage.RULE_BUILDER__FIELD_CLASS:
			setFieldClass((EClass) newValue);
			return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
		case BoardGamePackage.RULE_BUILDER__LAST_FIELD:
			setLastField((ObjectVariable) null);
			return;
		case BoardGamePackage.RULE_BUILDER__FIGURE_CLASS:
			setFigureClass((EClass) null);
			return;
		case BoardGamePackage.RULE_BUILDER__FIELD_CLASS:
			setFieldClass((EClass) null);
			return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
		case BoardGamePackage.RULE_BUILDER__LAST_FIELD:
			return lastField != null;
		case BoardGamePackage.RULE_BUILDER__FIGURE_CLASS:
			return figureClass != null;
		case BoardGamePackage.RULE_BUILDER__FIELD_CLASS:
			return fieldClass != null;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eInvoke(int operationID, EList<?> arguments)
			throws InvocationTargetException {
		switch (operationID) {
		case BoardGamePackage.RULE_BUILDER___TRANSFORM_FOLDER__FOLDER_EPACKAGE:
			return transformFolder((Folder) arguments.get(0),
					(EPackage) arguments.get(1));
		case BoardGamePackage.RULE_BUILDER___TRANSFORM_FILE__NODE:
			return transformFile((Node) arguments.get(0));
		case BoardGamePackage.RULE_BUILDER___EMBED__ACTIVITY_EANNOTATION:
			embed((Activity) arguments.get(0), (EAnnotation) arguments.get(1));
			return null;
		case BoardGamePackage.RULE_BUILDER___TRANSFORM_RULE__NODE:
			return transformRule((Node) arguments.get(0));
		case BoardGamePackage.RULE_BUILDER___TRANSFORM_FIELD__STORYPATTERN_OBJECTVARIABLE_NODE_NODE:
			return transformField((StoryPattern) arguments.get(0),
					(ObjectVariable) arguments.get(1), (Node) arguments.get(2),
					(Node) arguments.get(3));
		}
		return super.eInvoke(operationID, arguments);
	}

} //RuleBuilderImpl
